﻿using HPSocket;
using HPSocket.Tcp;
using MCMesServer.Model;
using MCMesServer.PublicLogInfo;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;

namespace MCMesServer.NetConnectFunc
{
    public class TcpServerConnect
    {
        public TcpPackServer tcpServer = new TcpPackServer();

        public TcpServerConnect(string ip, ushort port, bool exter = false)
        {
            tcpServer.SocketBufferSize = 1024 * 1024;
            tcpServer.MaxPackSize = 0x3FFFFF;
            tcpServer.OnPrepareListen += OnPrepareListen;
            tcpServer.OnAccept += OnAccept;
            tcpServer.OnClose += OnClose;
            tcpServer.OnReceive += OnReceive;

            tcpServer.OnSend += OnSend;
            tcpServer.OnShutdown += OnShutdown;

            tcpServer.Address = ip;
            tcpServer.Port = port;
            tcpServer.SendPolicy = HPSocket.SendPolicy.Pack;
        }

        public void StartConnect()
        {
            tcpServer?.Start();
        }

        /// <summary>
        /// 开始监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="listen"></param>
        /// <returns></returns>
        private HandleResult OnPrepareListen(IServer sender, IntPtr listen)
        {
            MainWindow.IsConnect = true;
            return HandleResult.Ok;
        }

        private HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr client)
        {
            return Task.Factory.StartNew(() =>
            {
                try
                {
                    if (tcpServer.Address == ConfigClass.ReadIniData("NetConnection", "ExServerAddress", MainWindow.ConfigPath))
                    {
                        return HandleResult.Ok;
                    }
                    if (!sender.GetRemoteAddress(connId, out var ip, out var port))
                    {
                        return HandleResult.Error;
                    }
                    string address = "";
                    ushort iport = 0;
                    sender.GetRemoteAddress(connId, out address, out iport);
                    string Net_Number = "";
                    foreach (var item in MainWindow.ServerAddress)
                    {
                        if (item.Value.Equals(address))
                        {
                            Net_Number = item.Key;
                        }
                    }

                    if (MainWindow.ServerLink.ContainsKey(Net_Number))
                    {
                        MainWindow.ServerLink[Net_Number] = connId;

                        //记录连接成功
                        PublicLogInfoFunc.RecordManualInfoMessage("连接", $"{Net_Number} 连接成功，连接ID:{connId}");
                    }
                    return HandleResult.Ok;
                }
                catch (Exception ex)
                {
                    PublicLogInfoFunc.RecordManualErrorMessage("连接", $"连接错误：{ex.ToString()}");
                    return HandleResult.Error;
                }
            }, TaskCreationOptions.LongRunning).Result;
        }

        public void SendClientModel(IntPtr connId, ClientModel model)
        {
            try
            {
                var serializer = new DataContractJsonSerializer(typeof(ClientModel));
                var stream = new MemoryStream();
                serializer.WriteObject(stream, model);
                byte[] dataBytes = new byte[stream.Length];

                stream.Position = 0;
                stream.Read(dataBytes, 0, (int)stream.Length);

                tcpServer.Send(connId, dataBytes, dataBytes.Length);
            }
            catch (Exception ex)
            {
                PublicLogInfoFunc.RecordManualErrorMessage("发送序列化", ex.ToString());
            }
        }

        public void SendServerModel(IntPtr connId, ServerModel model)
        {
            try
            {
                var serializer = new DataContractJsonSerializer(typeof(ServerModel));
                var stream = new MemoryStream();
                serializer.WriteObject(stream, model);
                byte[] dataBytes = new byte[stream.Length];

                stream.Position = 0;
                stream.Read(dataBytes, 0, (int)stream.Length);

                tcpServer.Send(connId, dataBytes, dataBytes.Length);
            }
            catch (Exception ex)
            {
                PublicLogInfoFunc.RecordManualErrorMessage("发送序列化", ex.ToString());
            }
        }

        /// <summary>
        /// 关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="socketOperation"></param>
        /// <param name="errorCode"></param>
        /// <returns></returns>
        private HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
        {
            try
            {
                string address = "";
                ushort port = 0;
                sender.GetRemoteAddress(connId, out address, out port);

                string Net_Number = "";
                foreach (var item in MainWindow.ServerAddress)
                {
                    if (item.Value.Equals(address))
                    {
                        Net_Number = item.Key;
                    }
                }

                if (MainWindow.ServerLink.ContainsKey(Net_Number))
                {
                    MainWindow.ServerLink[Net_Number] = IntPtr.Zero;
                    PublicLogInfoFunc.RecordManualInfoMessage("连接", $"{Net_Number} IP地址：{address} 连接断开");
                    return HandleResult.Ok;
                }
                else
                {
                    return HandleResult.Error;
                }
            }
            catch (Exception)
            {
                return HandleResult.Error;
            }
        }

        /// <summary>
        /// 接收到来自客户端的信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="connId"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private HandleResult OnReceive(IServer sender, IntPtr connId, byte[] data)
        {
            try
            {
                PublicLogInfoFunc.RecordManualInfoMessage("接收序列化", $"序列化长度：{data.Length}");
                var mStream = new MemoryStream(data);
                var serializer = new DataContractJsonSerializer(typeof(ServerModel));
                ServerModel readConfig = (ServerModel)serializer.ReadObject(mStream);

                CommonConnectFunc.ReceiveMessageHandler(tcpServer, readConfig, connId);
                return HandleResult.Ok;
            }
            catch (Exception ex)
            {
                PublicLogInfoFunc.RecordManualErrorMessage("接收文件反序列化", ex.ToString());
                return HandleResult.Error;
            }
        }

        private HandleResult OnSend(IServer sender, IntPtr connId, byte[] data)
        {
            return HandleResult.Ok;
        }

        private HandleResult OnShutdown(IServer sender)
        {
            try
            {
                return HandleResult.Ok;
            }
            catch (Exception ex)
            {
                return HandleResult.Error;
            }
        }
    }
}
